//**************************************************************************/
// Copyright (c) 1998-2007 Autodesk, Inc.
// All rights reserved.
// 
// These coded instructions, statements, and computer programs contain
// unpublished proprietary information written by Autodesk, Inc., and are
// protected by Federal copyright law. They may not be disclosed to third
// parties or copied or duplicated in any form, in whole or in part, without
// the prior written consent of Autodesk, Inc.
//**************************************************************************/
// DESCRIPTION: Appwizard generated plugin
// AUTHOR: 
//***************************************************************************/

#include "[!output PROJECT_NAME].h"

#define [!output CLASS_NAME]_CLASS_ID	Class_ID([!output CLASSID1], [!output CLASSID2])

#define PBLOCK_REF	0

class [!output CLASS_NAME] : public [!output SUPER_CLASS_NAME]
{
public:
	//Constructor/Destructor
	[!output CLASS_NAME]();
	virtual ~[!output CLASS_NAME]();

	// Effect class methods
	virtual TSTR GetName() { return GetString(IDS_CLASS_NAME); }
	virtual EffectParamDlg* CreateParamDialog( IRendParams* pParams );
	virtual int RenderBegin( TimeValue t, ULONG flags );
	virtual int RenderEnd( TimeValue t );
	virtual void Update( TimeValue t, Interval& valid );
	virtual void Apply( TimeValue t, Bitmap *pBM, RenderGlobalContext *pGC, CheckAbortCallback *checkAbort);

	// Loading/Saving
	virtual IOResult Load(ILoad *iload);
	virtual IOResult Save(ISave *isave);

	//From Animatable
	virtual Class_ID ClassID() {return [!output CLASS_NAME]_CLASS_ID;}
	virtual SClass_ID SuperClassID() { return RENDER_EFFECT_CLASS_ID; }
	virtual void GetClassName(TSTR& s) {s = GetString(IDS_CLASS_NAME);}

	virtual RefTargetHandle Clone( RemapDir &remap );
	virtual RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID,  RefMessage message);

	virtual int NumSubs() { return 1; }
	virtual TSTR SubAnimName(int /*i*/) { return GetString(IDS_PARAMS); }
	virtual Animatable* SubAnim(int /*i*/) { return pblock; }

	// TODO: Maintain the number or references here
	virtual int NumRefs() { return 1; }
	virtual RefTargetHandle GetReference(int);

	virtual int NumParamBlocks() { return 1; }					// return number of ParamBlocks in this instance
	virtual IParamBlock2* GetParamBlock(int /*i*/) { return pblock; } // return i'th ParamBlock
	virtual IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : NULL; } // return id'd ParamBlock

	virtual void DeleteThis() { delete this; }

protected:
	virtual void SetReference(int i, RefTargetHandle rtarg);

private:
	// Parameter block
	IParamBlock2* pblock; //ref 0
};



[!output TEMPLATESTRING_CLASSDESC]


[!if PARAM_MAPS != 0]
[!output TEMPLATESTRING_PARAMBLOCKDESC]
[!endif]


[!output CLASS_NAME]::[!output CLASS_NAME]()
	: pblock(nullptr)
{
	Get[!output CLASS_NAME]Desc()->MakeAutoParamBlocks(this);
}

[!output CLASS_NAME]::~[!output CLASS_NAME]()
{
}


/*===========================================================================*\
 |	Standard Load
\*===========================================================================*/

IOResult [!output CLASS_NAME]::Load(ILoad* iload)
{
	Effect::Load(iload);
	return IO_OK;
}

IOResult [!output CLASS_NAME]::Save(ISave* isave)
{
	Effect::Save(isave);
	return IO_OK;
}

RefTargetHandle [!output CLASS_NAME]::Clone( RemapDir &remap )
{
	[!output CLASS_NAME]* newObj = new [!output CLASS_NAME]();
	newObj->ReplaceReference(0,remap.CloneRef(pblock));
	BaseClone(this, newObj, remap);
	return (RefTargetHandle)newObj;
}
/*===========================================================================*\
 |	Ask the ClassDesc2 to make the AUTO_UI [!output CLASS_NAME]DlgProc
\*===========================================================================*/

EffectParamDlg *[!output CLASS_NAME]::CreateParamDialog(IRendParams* ip)
{		
	return Get[!output CLASS_NAME]Desc()->CreateParamDialogs(ip, this);
}

void [!output CLASS_NAME]::SetReference(int i, RefTargetHandle rtarg)
{
	if (i == PBLOCK_REF)
	{
		pblock=(IParamBlock2*)rtarg;
	}
}

RefTargetHandle [!output CLASS_NAME]::GetReference( int i)
{
	if (i == PBLOCK_REF)
	{
		return pblock;
	}
	return nullptr;
}

RefResult [!output CLASS_NAME]::NotifyRefChanged(
		Interval /*changeInt*/, RefTargetHandle hTarget,
		PartID& /*partID*/,  RefMessage message) 
{
	switch (message) {
		case REFMSG_CHANGE:
			[!output CLASS_NAME_LOWER]_param_blk.InvalidateUI();
			break;
		case REFMSG_TARGET_DELETED:
			{
				if (hTarget == pblock)
				{
					pblock = nullptr;
				}
			}
			break;
	}
	return REF_SUCCEED;
}


/*===========================================================================*\
 |	This method is called once per frame when the renderer begins.  
\*===========================================================================*/

void [!output CLASS_NAME]::Update(TimeValue /*t*/, Interval& /*valid*/)
{
	//TODO: Implement the actual effect
}


/*===========================================================================*\
 |	Called to initialize or clear up before and after rendering  
\*===========================================================================*/

int [!output CLASS_NAME]::RenderBegin(TimeValue /*t*/, ULONG /*flags*/)
{
	return 0;
}

int [!output CLASS_NAME]::RenderEnd(TimeValue /*t*/)
{
	return 0;
}

/*===========================================================================*\
 |	Apply the actual changes to the rendered bitmap at time 't'
 *===========================================================================*/

void [!output CLASS_NAME]::Apply(TimeValue /*t*/, Bitmap* /*bm*/, RenderGlobalContext* /*gc*/,CheckAbortCallback* /*checkAbort*/ ) 
{

}

